package com.bookstore.service.impl;

import com.bookstore.service.BaseService;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.List;
import java.util.stream.Collectors;

/**
 * 通用服务实现类，实现基本的CRUD操作
 * @param <T> 实体类型
 * @param <D> DTO类型
 * @param <ID> ID类型
 * @param <R> Repository类型
 */
public abstract class BaseServiceImpl<T, D, ID, R extends JpaRepository<T, ID>> implements BaseService<T, D, ID> {
    
    protected final R repository;
    
    public BaseServiceImpl(R repository) {
        this.repository = repository;
    }
    
    /**
     * 将实体转换为DTO
     * @param entity 实体
     * @return DTO
     */
    protected abstract D convertToDTO(T entity);
    
    /**
     * 将DTO转换为实体
     * @param dto DTO
     * @return 实体
     */
    protected abstract T convertToEntity(D dto);
    
    /**
     * 更新实体
     * @param entity 现有实体
     * @param dto 新DTO
     */
    protected abstract void updateEntity(T entity, D dto);
    
    @Override
    public List<D> findAll() {
        return repository.findAll().stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
    }
    
    @Override
    public Page<D> findAll(Pageable pageable) {
        return repository.findAll(pageable)
                .map(this::convertToDTO);
    }
    
    @Override
    public D findById(ID id) {
        return repository.findById(id)
                .map(this::convertToDTO)
                .orElseThrow(() -> new RuntimeException("Entity not found"));
    }
    
    @Override
    public D save(D dto) {
        T entity = convertToEntity(dto);
        T savedEntity = repository.save(entity);
        return convertToDTO(savedEntity);
    }
    
    @Override
    public D update(ID id, D dto) {
        return repository.findById(id)
                .map(entity -> {
                    updateEntity(entity, dto);
                    return convertToDTO(repository.save(entity));
                })
                .orElseThrow(() -> new RuntimeException("Entity not found"));
    }
    
    @Override
    public void delete(ID id) {
        repository.deleteById(id);
    }
}